#include "xFileParse.h"
#include "xShaderManager.h"
#include "xTextureManager.h"
#include "xTexture.h"
#include "xMaterial.h"


namespace XE	
{


	xFileParse::xFileParse(const  xString& name)
		:m_FileName(name.c_str()),m_pdoc(NULL)
	{
		//RegisterParseFun();
		m_pdoc = new TiXmlDocument(name.c_str());

	}


	xFileParse::~xFileParse()
	{
		SafeDelete(m_pdoc)
	}

	bool xFileParse::LoadFile()
	{
		return  m_pdoc->LoadFile();
	}



	bool  xFileParse::GetRootNodeName(xString& name)
	{
		if(m_pdoc==NULL)
			return false;
		TiXmlElement* pRoot = m_pdoc->RootElement();
		if(pRoot==NULL)
			return false;
		name = pRoot->Value();
		return true;

	}




	bool  xFileParse::Parse()
	{
		TiXmlElement* pRootElement =  m_pdoc->RootElement();
		if(pRootElement!=NULL)
		{
			if(ParseElement( pRootElement)==false)
				return false;
		}

		EndParse();

		return true;
	}


	bool xFileParse::ParseElement( TiXmlElement* pElement)
	{
		if(pElement==NULL)
			return false;

		xString ElementValue = pElement->Value();
	/*	xString ElementText;
		if(pElement->GetText()!=NULL)
		{
			ElementText = pElement->GetText();
		}*/

		BeginParseElement(ElementValue,pElement);

		CallParseElement(ElementValue,pElement);

		TiXmlAttribute*  pFristAttribute  =  pElement->FirstAttribute();
		while(pFristAttribute!=NULL)
		{
			xString attrName =   pFristAttribute->Name();
			xString attrValue =  pFristAttribute->Value();

			CallParseAttribute(ElementValue,attrName,attrValue);
			pFristAttribute=pFristAttribute->Next();

		}


		TiXmlElement*pChild = pElement->FirstChildElement();

		while(pChild!=NULL)
		{
			ParseElement(pChild);
			pChild = pChild->NextSiblingElement();
		}


		EndParseElement(ElementValue,pElement);

	/*	TiXmlElement* pSibElement = pElement->NextSiblingElement();
		while(pSibElement!=NULL)
		{
			ParseElement(pSibElement);
			pSibElement = pSibElement->NextSiblingElement();
		}*/

       


		return true;
	}

	//bool  xFileParse::RegisterParseFun()
	//{

	////	AddElementParseFun("xMaterial", &xFileParse::ParseMaterial);

	//	//AddAttributeParseFun("name",&xFileParse::ParseParameter);

	//	return true;
	//}



	void xFileParse::AddElementParseFun(const xString&name,ParseElementFun fun)
	{
		m_ElementParseFun[name.c_str()] = fun;
		return ;
	}


	void xFileParse::AddAttributeParseFun(const xString& attributeName,ParseAttributeFun fun)
	{
		m_AttributeParseFun[attributeName.c_str()] = fun;
		return ;
	}


	void  xFileParse::CallParseElement( const xString& ElementName,TiXmlElement*pElement)
	{
		ParseElementFunMap::iterator it = m_ElementParseFun.find(ElementName);
		if(it!=m_ElementParseFun.end()&&it->second!=NULL)
		{
			ParseElementFun fun = it->second;
			(this->*(fun))(ElementName,pElement);			
		}
		return ;
	}

	void xFileParse::CallParseAttribute\
		(const xString& ElementName,const xString& AttributeName,const xString& AttributeValue)
	{
		ParseAttributeFunMap::iterator it = m_AttributeParseFun.find(AttributeName);
		if(it!=m_AttributeParseFun.end()&&it->second!=NULL)
		{
			ParseAttributeFun fun = it->second;
			(this->*(fun))(ElementName,AttributeName,AttributeValue);
		}
	}




//---------------------------------------------------------------------------------
	xMaterialFileParse::xMaterialFileParse(const xString& FileName,xMaterial*	 mat)
		:xFileParse(FileName),m_pMaterial(mat),m_pTechnique(NULL),m_pShaderParamenter(NULL)
	{
		AddElementParseFun("xMaterial",static_cast<ParseElementFun>(&xMaterialFileParse::ParseMaterial));
		AddElementParseFun("ShaderParament",static_cast<ParseElementFun>(&xMaterialFileParse::ParseShaderParament));
		AddAttributeParseFun("name",static_cast<ParseAttributeFun>(&xMaterialFileParse::ParseMaterialName));
		AddAttributeParseFun("distance",static_cast<ParseAttributeFun>(&xMaterialFileParse::ParseTechniqueDistance));
		AddAttributeParseFun("filename",static_cast<ParseAttributeFun>(&xMaterialFileParse::ParseShaderFile));
		//AddAttributeParseFun("filename",static_cast<ParseAttributeFun>(&xMaterialFileParse::ParseTextureFile));

		assert(mat!=NULL);
		mat->ClearAllRenderScheme();
		

		
	}



	void xMaterialFileParse::ParseMaterial(const xString& elementName,TiXmlElement*pElement)
	{

		


	}

	 void xMaterialFileParse::ParseMaterialName\
		 (const xString& elementname,const xString& AttributeName,const xString& AttValue)
	 {


    //      xResourceCreateParameter matrParameter(AttValue);
		  //m_pMaterial=static_cast<xMaterial*>(xMaterialManager::getSingleton().CreateResource(&matrParameter));
		  //if(m_pMaterial==NULL)
		  //{

		  //}


	 }


	 void xMaterialFileParse::ParseTechniqueDistance\
		 (const xString& elementname,const xString& AttributeName,const xString& AttValue)
	 {
		 float distance  = xHelp::StringTofloat(AttValue);
		 if(m_pMaterial!=NULL)
		 {
			m_pTechnique= m_pMaterial->CreateRenderScheme(distance,xShaderPtr());
		 }

	 }



	 void xMaterialFileParse::ParseShaderFile\
		 (const xString& elementName,const xString& Attributename,const xString& AttrValue)
	 {


		 if(m_pTechnique!=NULL)
		 {
			 if(elementName=="shader")
			 {

				 m_pShader  = xShaderManager::getSingleton().GetByName(AttrValue);
				 if(m_pShader.isNull())
				 {
					 m_pShader =xShaderManager::getSingleton().CreateResource(AttrValue,AttrValue);
				 }
		

				 m_pTechnique->SetShader(m_pShader);

				 
			 }else if(elementName=="texture")
			 {


				 xTexturePtr pTexture  = xTextureManager::getSingleton().GetByName(AttrValue);
				 if(pTexture.isNull())
				 {

					pTexture= xTextureManager::getSingleton().CreateResource(AttrValue,AttrValue);
				 }
				 
				 int textureCount =  m_pTechnique->GetTexutreNumber();
				 m_pTechnique->SetTexture(textureCount,pTexture);

			 }
			
		 }
	 }



	  void xMaterialFileParse::ParseShaderParament(const xString&Name,TiXmlElement*pElement)
	  {
		  if(pElement==NULL||m_pTechnique==NULL)
			  return ;

		  const char* pName =  pElement->Attribute("Name");
		  if(pName==NULL)
		  {
			  xLogMessager::getSingleton().logMessage(xString("parse Shader parameter can not find Name,file name is")\
				  +pElement->GetDocument()->Value());
			  return ;
		  }
		  
		  const char* pStrType = pElement->Attribute("Type");
		  if(pStrType==NULL)
		  {
			  xLogMessager::getSingleton().logMessage(xString("parse Shader parameter can not find Type,file name is")\
				  +pElement->GetDocument()->Value());
			  return ;
		  }

		  const char* pValue = pElement->Attribute("Value");
		  if(pValue==NULL)
		  {
			  xLogMessager::getSingleton().logMessage(xString("parse Shader parameter can not find Value,file name is")\
				  +pElement->GetDocument()->Value());
			  return ;
		  }


		  XSHADERPARAMETER_TYPE type;
		  xString ParameterType = pStrType;
		  int size = 0;
		  char* pData = NULL;
		  if(ParameterType=="float4")
		  {
			  type = XSPT_FLOAT;
			  xVector4 Value =  xHelp::StringToVector4(pValue);
			  pData = (char*)(new xVector4(Value));
			  size = sizeof(float)*4;
		  }else if(ParameterType=="float3")
		  {
			  type=XSPT_FLOAT;
			  xVector3 Value = xHelp::StringToVector3(pValue);
			  size = sizeof(float)*3;
		  }

		  xShaderParameter* pPara= m_pTechnique->GetParameterByName(pName);
		  if(pPara!=NULL&&pData!=NULL)
		  {
			  pPara->WriteData(pData,size);
		  }

		  SafeDelete(pData);

		
  //m_pTechnique->CreateParameter(pName,"",)

	  }

}